昨天我們做了一個不能點的 neuomorphic-button
今天我們把他可以點擊 & 加上 shadow-dom 讓元件內外的 styling 區隔開來吧 !
昨天我們做了一個不能點的 neuomorphic-button 元件 
// neuomorphic-button.js
class NeuomorphicButton extends HTMLElement {
  // as Component mounted to page
  constructor() {
    // Always call super first in constructor
    super();
    // Element functionality written in here
    const div = document.createElement('div')
    div.classList.add('icon-box')
    div.innerHTML = `<i class="fas fa-wifi"></i>`
    this.append(div)
  }
}
window.customElements.define('neuomorphic-button', NeuomorphicButton);
首先我們先補上 checkbox 讓其可以被點擊 ,
 因為我們要客製化 checkbox 的樣式 , 因此會需要設定 checkbox 的樣式為 display:none 把它隱藏起來
 這時我們可以請出 label 這個 Html tag , 用 label 將 input 元素包住 , 將 onclick 事件轉送到 input[type="checkbox"] 上
// neuomorphic-button.js
class NeuomorphicButton extends HTMLElement {
  constructor() {
    super();
    // 利用 div 顯示按鈕的樣式
    const div = document.createElement('div')
    div.classList.add('icon-box')
    div.innerHTML = `<i class="fas fa-wifi"></i>`
    // label & 其內部的 checkbox
    const label = document.createElement('label')
    label.innerHTML = `<input type="checkbox">`
    label.append(div)
    this.append(label)
  }
}
window.customElements.define('neuomorphic-button', NeuomorphicButton);
當然在 html 中我們需要補上一些樣式設定
<style>
    /* neuomorphic-button 的樣式 */
    label input[type='checkbox'] {
      display: none;
    }
    label .icon-box {
      width: 60px;
      height: 60px;
      position: relative;
      background-color: #ebf5fc;
      box-shadow: 8px 8px 16px #bcbcbc,
      -8px -8px 16px #ffffff;
      display: flex;
      justify-content: center;
      align-items: center;
      border-radius: 10px;
      cursor: pointer;
      transition:all 0.3s;
    }
    label .icon-box:hover {
      transform:translateY(3px)
    }
    label .icon-box i {
      font-size: 2em;
      color: #6a9bd8;
    }
    // 被點選後的樣式
    label input[type='checkbox']:checked ~ .icon-box {
      box-shadow: inset -2px -2px 5px rgba(255, 255, 255, 1),
      inset 3px 3px 5px rgba(0, 0, 0, 0.1);
    }
    label input[type='checkbox']:checked ~ .icon-box i {
      transform: scale(0.95);
      filter: hue-rotate(90deg);
    }
  </style>
之後我們得到了一個可點擊的 neuomorphic-button

目前我們的 style 是定義在 html 的 header 中 , 如果有其他的 css 設定可能會造成互相影響
這時我們就可以請出 shadow dom 來 ~~~
const shadowRoot = this.attachShadow({mode: 'open'})
既然我們都改用 shadow dom 那當然需要將掛在 this 上的那些 HTML 元素 , 改掛在 shadowRoot 的上面
// neuomorphic-button.js
class NeuomorphicButton extends HTMLElement {
  // as Component mounted to page
  constructor() {
    ...跟之前相同的設定
    // 將 label 改 append 到 shadowRoot 上面
    const shadowRoot = this.attachShadow({mode: 'open'})
    shadowRoot.append(label)
  }
}
window.customElements.define('neuomorphic-button', NeuomorphicButton);
改後我們會獲得以下截圖

奇怪 , 外部有定義樣式阿 ~ , 那 neuomorphic-button 元件內的樣式為何會沒有吃到呢 ?
原來 shadow dom 也就是 this.attachShadow({mode: 'open'}) 會將 shadowRoot 中的樣式跟外部 Html 的樣式做一個區隔
所以 , 我們需要在 shadowRoot 的內部再定義一次樣式
// neuomorphic-button.js
class NeuomorphicButton extends HTMLElement {
  // as Component mounted to page
  constructor() {
    ...跟之前相同的設定
     // 將樣式相關的部分 , 定義在此
+    const fontAwesomeStyle = `<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css">`
+    const styleStr =  'neuomorphic-button 的樣式'
    // 將 label 改 append 到 shadowRoot 上面
    const shadowRoot = this.attachShadow({mode: 'open'})
+    shadowRoot.innerHTML = fontAwesomeStyle + styleStr  // 將定義出來的樣式 , 掛載到 shadowRoot 內部
    shadowRoot.append(label)
  }
}
window.customElements.define('neuomorphic-button', NeuomorphicButton);
太棒了 ! 按鈕吃到我們設定的樣式了 (^∀^●)ノシ

如果想查看實際頁面 , 請到 shadow-dom.html 查看
下方情況 label 會將 onclick 事件做一個轉送 , 事件將傳給對應的元素並觸發其 onclick
A. for 對應的那個 name HTML 元素
<div class="preference">
    <label for="cheese">Do you like cheese?</label>
    <input type="checkbox" name="cheese" id="cheese">
</div>
B. 包在 label 內的 input 元素
<label>
  <input type="checkbox">
  I agree to the Terms and Conditions
</label>
因此我們需要利用 隱藏原生 checkbox + 設定 div 樣式 來製作自身想要的 checkbox
<label>
  <!-- 隱藏原生 checkbox -->
  <input type="checkbox" style="display:none">
  
  <!-- 將想要的 checkbox 樣式設定在 myCheckbox 中 -->
  <div class="myCheckbox">
</label>
詳細的 Styling checkbox 步驟請參考 這篇